#pragma once

#include "d3dUtil.h"

//prototypes to keep compiler from whining
class MissileTrail;
class BaseMissile;
class BasicThruster;
class TestShip;
class BasicShip;
class Explosion;
class ThrusterEffect;
class Bot;

#include "DirectXFramework.h"

struct Particle
{
	D3DXVECTOR3 Position;
	D3DXVECTOR3 Velocity;
	D3DXCOLOR Color;
	float StartTime;
	float LifeTime;
};


class ParticleSystem
{
protected:
	int MaxParticles;
	float Time;
protected:
	std::vector<Particle*>DeadParticles;
	IDirect3DDevice9* EffectDevice;

	float TimePerParticle;

	IDirect3DVertexBuffer9* VertexBuffer;

	D3DXHANDLE Technique;
	D3DXHANDLE WorldViewProjection;
	D3DXHANDLE ViewportHeight;
	D3DXHANDLE EyeHandle;

	D3DXMATRIX WorldMat;
	D3DXMATRIX InverseWorldMat;
	D3DXMATRIX WVPMat;

	D3DXVECTOR3 CameraPosition;
	D3DXVECTOR3 Position;
	
	IDirect3DVertexDeclaration9* decl;

public:
	std::vector<Particle*>AliveParticles;
	std::vector<Particle> Particles;
	ID3DXEffect* Effect;
	ParticleSystem();
	ParticleSystem(IDirect3DDevice9* InitialDevice, const std::string EffectFileName,const std::string techniqueName,
		D3DXVECTOR3 nPosition, int MaximumParticles, float nTimePerParticle = 0.0);
	virtual ~ParticleSystem( void );

	float GetTime( void );
	void SetTime( float nTime);

	void SetWorldMatrix(const D3DXMATRIX& world);
	void SetWVPMatrix(const D3DXMATRIX &nWVP);
	void SetCameraPosition(const D3DXVECTOR3 &nCameraPosition);

	void AddParticle( void );

	virtual void onResetDevice( void );
	virtual void onLostDevice( void );

	virtual void initParticle(Particle &out) = 0;

	D3DXVECTOR3 GetPosition( void ){return Position;};
	void SetPosition(D3DXVECTOR3 nPosition);

	void Update(float dt);
	void Render();
};

class MissileTrail : public ParticleSystem
{
private:
	bool IsActive;
	bool OldActive;

	D3DXVECTOR3 Angles;
	D3DXVECTOR3 SpawnVector;
	D3DXVECTOR3 StartPosition;
	D3DXMATRIX RotationMatrix;

public:
	MissileTrail();
	MissileTrail(IDirect3DDevice9* InitialDevice, const std::string EffectFileName,const std::string techniqueName,
		D3DXVECTOR3 nPosition, int MaximumParticles, float nTimePerParticle = 0.0);

	~MissileTrail();

	void initParticle(Particle &out);
	//void initParticle(Particle &out, float nThrust);

	void SetAngles(D3DXVECTOR3 nAngles);
	bool GetOldActive( void );

	void Reset( void );

	void Update( float dt);
	void Render( void );
	void Activate( void );
	void Deactivate( void );
	bool GetIsActive( void );
};

class ThrusterEffect : public ParticleSystem
{
private:
	bool IsActive;

	short Throttle;

	D3DXVECTOR3 Angles;
	D3DXVECTOR3 SpawnVector;
	D3DXVECTOR3 SpawnVelocity;
	D3DXVECTOR3 StartPosition;
	D3DXMATRIX RotationMatrix;

public:
	ThrusterEffect();
	ThrusterEffect(IDirect3DDevice9* InitialDevice, const std::string EffectFileName,const std::string techniqueName,
		D3DXVECTOR3 nPosition, int MaximumParticles, float nTimePerParticle = 0.0);

	~ThrusterEffect();

	void initParticle(Particle &out);

	void SetAngles(D3DXVECTOR3 nAngles);

	void SetThrottle( short nThrottle);
	void SetSpawnVelocity( D3DXVECTOR3 nSpawnVelocity);

	void Update( float dt);
	void Render( void );
	void Activate( void );
	void Deactivate( void );
	bool GetIsActive( void );
};

class Explosion : public ParticleSystem
{
private:
	bool IsActive;
	float ParticleLifeTime;
	bool RenewExplosion;
	D3DXHANDLE gTime;

public:
	Explosion();
	Explosion(IDirect3DDevice9* InitialDevice, const std::string EffectFileName,const std::string techniqueName,
		D3DXVECTOR3 nPosition, int MaximumParticles, float nTimePerParticle = 0.0);

	void initParticle( Particle &out );

	void Activate( void );
	void Deactivate( void );

	bool GetIsActive( void );

	virtual void Update(float dt);
	virtual void Render(void);

	void Reset( void );
};
extern CDirectXFramework *gd3dApp;